from django.shortcuts import render

# Create your views here.

# views.py
from admins.models import (
    RoleModel,
    AdminUserModel,
    ResourceModel,
    ResourceInterface,
    MutexModel
)
from admins.ser import (
    ResourceSerializer,
    RoleSerializer,
    AdminUserSerializer,
    ResourceInterfaceSerializer,
    MutexSerializer
)

from rest_framework import generics
from rest_framework.generics import ListAPIView, CreateAPIView, DestroyAPIView, RetrieveAPIView, UpdateAPIView, RetrieveUpdateAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import TokenAuthentication

import time, json
from tools.myjwt import mjwt
from tools.myredis import r
from django_redis import get_redis_connection

# ================================================================== 登录 ==================================================================

# 管理员登录视图
class LoginView(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        password = request.data.get('password')
        admin = AdminUserModel.objects.filter(phone=phone, password=password).first()

        if admin:
            # 1080s
            # 设置token载荷及其过期时间
            token = mjwt.jwt_encode({'data': {'id': admin.id, 'role': admin.role.id, 'exp': int(time.time()) + 10800}})
            role_id = admin.role_id
            # if role_id == 1:
            # 获取角色对应资源
            role = RoleModel.objects.get(id=role_id)
            resources_list = ResourceModel.objects.filter(id=role_id).values()
            resource = list(resources_list)
            resources = [{**{k: v for k, v in item.items() if k != 'pid_id'}, 'pid': item['pid_id']} for item in resource]
            for item in resources:
                item['pid'] = ResourceModel.objects.get(pk=item['pid'])
            # 打印转换后的结果
            serializer = ResourceSerializer(resource, many=True)

            # 修改返回格式
            data_list = []
            pid_list = []
            url_list = []  # 新增前端路由列表
            for i in serializer.data:
                data_list.append(
                    {"id": i["id"], "name": i["name"], "url": i["url"], "pid": i["pid"]})
                if {"pid": i["pid"], "son": []} not in pid_list:
                    pid_list.append({"pid": i["pid"], "son": []})

            for item in data_list:
                for j in pid_list:
                    if item["pid"] == j["pid"]:
                        j["son"].append({"id": item["id"], "name": item["name"], "url": item["url"]})
                        url_list.append(item["url"])
                        break
            # 使每个角色均可访问admin页
            url_list.append("/admin")

            # 获取资源的接口列表
            interface_list = []
            for i in resources:
                interfaces = ResourceInterface.objects.filter(resid=i['pid'])
                for j in interfaces:
                    interface_list.append(j.url)

            redis = get_redis_connection("admin")
            pipeline = redis.pipeline()
            pipeline.multi()
            pipeline.set(f"dingxiang_role_{role_id}", json.dumps({"role": role.id, "interface_list": interface_list}))
            pipeline.execute()

            return Response({'message': 'Login successful', 'admin': AdminUserSerializer(admin).data, "token": token,
                             "pid_list": pid_list, "url_list": url_list})
        else:
            return Response({'message': 'Invalid credentials'}, status=400)


    def get(self, request):
        phone = request.GET.get('phone')
        role_list = AdminUserModel.objects.filter(phone=phone)
        if role_list.exists():
            role = role_list.first().role  # 获取第一个匹配的用户角色
            res1 = role.resources.all()  # 获取角色关联的资源
            res2 = role.pid  # 获取角色的父角色
            res3 = res2.resources.all() if res2 else []  # 获取父角色关联的资源，如果父角色不存在则为空列表
            res = list(res1) + list(res3)  # 合并资源列表
            for i in res:
                return Response({"code": 200, "resources": ResourceSerializer(res, many=True).data})
        else:
            return Response({"code": 404, "message": "用户未找到"})

# 退出登录
class LogoutView(APIView):
    def post(self, request):
        token = request.data.get("token")
        admin_id = mjwt.jwt_decode(token)["data"]["id"]
        redis = get_redis_connection("admin")
        redis.set(f"dingxiang_admin_{admin_id}", token)
        return Response({'message': '退出登录成功'})

# ================================================================== 菜单 ==================================================================

# 菜单视图
class MenuListView(APIView):
    def get(self, request):
         # 获取用户的角色id
        role_id = request.GET.get('role_id')
        # 获取角色对应资源
        role = RoleModel.objects.get(id=role_id)
        resources = ResourceModel.objects.filter(id=role.id)
        serializer = ResourceSerializer(resources, many=True)

        # 修改返回格式
        data_list = []
        pid_list = []

        for i in serializer.data:
            data_list.append({"id": i["id"], "name": i["name"], "url": i["url"], "pid": i["pid"]})
            if {"pid": i["pid"], "son": []} not in pid_list:
                pid_list.append({"pid": i["pid"], "son": []})

        for item in data_list:
            for j in pid_list:
                if item["pid"] == j["pid"]:
                    j["son"].append({"id": item["id"], "name": item["name"], "url": item["url"]})
                    # print(pid_list)
                    break

        return Response({"mes":pid_list,"code":"200"})

# ================================================================== 用户 ==================================================================

# 用户 增删改查 分页、排序、过滤

class CreateAdminUserView(APIView):
    def post(self, request):
        serializer = AdminUserSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response({"data":serializer.data, "status":"201"})
        return Response({"data":serializer.errors, "status":"40T"})

class DeleteAdminUserView(APIView):
     def delete(self, request, pk):
        try:
            user = AdminUserModel.objects.get(pk=pk)
            user.delete()
            return Response({"message": "用户删除成功", "status":"200"})
        except AdminUserModel.DoesNotExist:
            return Response({"data":"用户未找到", "status":"404"})

class UpdateAdminUserView(APIView):
    def put(self, request, pk):
        try:
            user = AdminUserModel.objects.get(pk=pk)
            serializer = AdminUserSerializer(user, data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response({"mes":serializer.data,"code":"200"})
            return Response({"data":serializer.errors, "status":"400"})
        except AdminUserModel.DoesNotExist:
            return Response({"data":"用户未找到", "status":"404"})

class AdminUserListView(APIView):
    def get(self, request):
        # 分页处理
        paginator = PageNumberPagination()
        paginator.page_size = 10  # 每页显示的记录数，可按需调整

        # 获取排序参数，例如前端传来?ordering=name 表示按用户姓名排序
        ordering = request.query_params.get('ordering', 'id')

        # 初始化查询集为所有用户
        queryset = AdminUserModel.objects.all()

        # 构建过滤条件，获取前端传来的过滤参数
        filter_params = request.query_params.get('filter', '')
        if filter_params:
            # 假设过滤参数格式为 key:value 的形式，用逗号分隔多个条件，例如 name:张三,role_name:管理员
            filter_conditions = [f.strip().split(':') for f in filter_params.split(',')]
            q_objects = Q()
            for condition in filter_conditions:
                key, value = condition
                if key == 'phone':
                    q_objects &= Q(phone__icontains=value)
                elif key == 'name':
                    q_objects &= Q(name__icontains=value)
                elif key == 'role_name':
                    q_objects &= Q(role__name__icontains=value)
            queryset = queryset.filter(q_objects)

        # 应用排序
        queryset = queryset.order_by(ordering)

        # 进行分页操作
        result_page = paginator.paginate_queryset(queryset, request)

        # 序列化用户数据，这里假设你有对应的序列化器 UserSerializer，需自行定义
        serializer = AdminUserSerializer(result_page, many=True)
        # print(serializer.data)
        return Response({"data":serializer.data, "status":"200"})

# ================================================================== 角色 ==================================================================

# 角色 增删改查 继承 分页、排序、过滤

from rest_framework.pagination import PageNumberPagination
from django.db.models import Q
from django.core.paginator import Paginator   

# 为特定角色添加资源
class CreateRoleView(APIView):
    def post(self, request):
        name = request.data.get('name')
        pid = request.data.get('pid')
        type = request.data.get('type')
        resource_ids = request.data.get('resource_ids', [])  # 前端传来的资源 ID 列表

        # 检查角色名称唯一性
        if RoleModel.objects.filter(name=name).exists():
            return Response({"message": "角色名称已存在", "status":"400"})

        # 处理父级角色关联，如果有传入的父级 ID
        parent_role = None
        if pid:
            try:
                parent_role = RoleModel.objects.get(id=pid)
            except RoleModel.DoesNotExist:
                return Response({"message": "父级角色不存在", "status":"400"})

        # 检查资源互斥情况
        for resource_id in resource_ids:
            try:
                resource = ResourceModel.objects.get(id=resource_id)
                # 检查该资源与已分配给该角色（如果有父级继承资源）的资源是否互斥
                if parent_role:
                    inherited_resources = parent_role.resources.all()
                    for inherited_resource in inherited_resources:
                        if MutexModel.objects.filter(
                                (Q(resource1=inherited_resource) & Q(resource2=resource)) |
                                (Q(resource1=resource) & Q(resource2=inherited_resource))
                        ).exists():
                            return Response({"message": f"资源 {resource.name} 与继承资源存在互斥", "status":"400"})
            except ResourceModel.DoesNotExist:
                return Response({"message": "资源不存在", "status":"400"})
        # 创建角色实例
        role = RoleModel(
            name=name,
            pid=parent_role,
            type=type
        )
        role.save()
        # 关联资源
        role.resources.set(resource_ids)
        return Response({"message": "角色创建成功", "role_id": role.id, "status":"201"})

# 更新特定角色的资源列表
class UpdateRoleView(APIView):
    def put(self, request, role_id):
        try:
            role = RoleModel.objects.get(id=role_id)
        except RoleModel.DoesNotExist:
            return Response({"message": "角色不存在", "status":"404"})

        name = request.data.get('name')
        type = request.data.get('type')
        resource_ids = request.data.get('resource_ids', [])  # 新的资源 ID 列表

        # 检查角色名称唯一性（如果名称有更改）
        if name and name!= role.name and RoleModel.objects.filter(name=name).exists():
            return Response({"message": "角色名称已存在", "status":"400"})

        # 处理资源变更及互斥检查
        current_resources = role.resources.all()
        resources_to_add = [r for r in resource_ids if r not in current_resources.values_list('id', flat=True)]
        resources_to_remove = [r for r in current_resources.values_list('id', flat=True) if r not in resource_ids]

        for resource_id in resources_to_add:
            try:
                resource = ResourceModel.objects.get(id=resource_id)
                # 检查与当前已有资源是否互斥
                for current_resource in current_resources:
                    if MutexModel.objects.filter(
                            (Q(resource1=current_resource) & Q(resource2=resource)) |
                            (Q(resource1=resource) & Q(resource2=current_resource))
                    ).exists():
                        return Response({"message": f"资源 {resource.name} 与已有资源存在互斥", "status":"400"})
            except ResourceModel.DoesNotExist:
                return Response({"message": "资源不存在", "status":"400"})

        # 更新角色自身属性
        role.name = name if name else role.name
        role.type = type if type else role.type
        role.save()

        # 更新资源关联
        role.resources.set(resource_ids)

        return Response({"message": "角色更新成功", "status":"200"})

# 删除特定角色
class DeleteRoleView(APIView):
    def delete(self, request, role_id):
        try:
            role = RoleModel.objects.get(id=role_id)
        except RoleModel.DoesNotExist:
            return Response({"message": "角色不存在", "status":"404"})

        # 检查是否有用户关联该角色，如果有，根据业务需求决定如何处理，这里简单返回提示
        if AdminUserModel.objects.filter(role=role).exists():
            return Response({"message": "存在关联用户，不能直接删除角色", "status":"400"})

        role.delete()

        return Response({"message": "角色删除成功", "status":"204"})

# 创建新角色及分页查询角色列表
class RoleListView(APIView):
    def get(self, request):
        # 分页
        paginator = PageNumberPagination()
        paginator.page_size = 10  # 每页显示的记录数，可以根据需求调整

        # 获取排序参数，例如前端传来?ordering=name 表示按名称排序
        ordering = request.query_params.get('ordering', 'id')

        # 过滤参数构建，初始查询集为所有角色
        queryset = RoleModel.objects.all()
        filter_params = request.query_params.get('filter', '')
        if filter_params:
            # 假设过滤参数格式为 key:value 的形式，用逗号分隔多个条件，例如 name:admin,type:super
            filter_conditions = [f.strip().split(':') for f in filter_params.split(',')]
            q_objects = Q()
            for condition in filter_conditions:
                key, value = condition
                if key == 'name':
                    q_objects &= Q(name__icontains=value)
                elif key == 'type':
                    q_objects &= Q(type__icontains=value)
                # 可以添加更多基于关联模型属性的过滤条件，比如按关联资源名称过滤
                elif key =='resource_name':
                    q_objects &= Q(resources__name__icontains=value)
            queryset = queryset.filter(q_objects)

        # 应用排序
        queryset = queryset.order_by(ordering)

        # 进行分页
        result_page = paginator.paginate_queryset(queryset, request)

        # 序列化角色数据，这里假设你有对应的序列化器 RoleSerializer，需自行定义
        serializer = RoleSerializer(result_page, many=True)
        # print(serializer.data)
        return Response({'mes':serializer.data, 'status':'200'})

# ================================================================== 资源 ==================================================================

# 资源 增删改查 互斥 分页、排序、过滤

# 获取所有非顶层资源的列表
class ResourceListView(ListAPIView):
    serializer_class = ResourceSerializer

    def get_queryset(self):
        queryset = ResourceModel.objects.exclude(pid=None)
        resource_list = list(queryset)
        reresources_list = list(ResourceModel.objects.filter(pid=None))
        return resource_list

# 根据角色ID获取资源列表，并构建资源树结构，同时生成前端路由列表
class GetResourceAPIView(APIView):
    def post(self, request):
        role_id = request.data.get('role_id')
        role = RoleModel.objects.get(id=role_id)
        resources = role.resources.all()
        serializer = ResourceSerializer(resources, many=True)

        data_list = []
        pid_list = []
        url_list = []  # 新增前端路由列表
        for i in serializer.data:
            data_list.append({"id": i["id"], "name": i["name"], "url": i["url"], "pid": i["pid"]})
            if {"pid": i["pid"], "son": []} not in pid_list:
                pid_list.append({"pid": i["pid"], "son": []})
        
        for item in data_list:
            for j in pid_list:
                if item["pid"] == j["pid"]:
                    j["son"].append({"id": item["id"], "name": item["name"], "url": item["url"]})
                    url_list.append(item["url"])
                    break
        url_list.append("/admin")
        print(url_list)
        print(pid_list)
        print(data_list)
        return Response({"data_list": data_list, "pid_list": pid_list, "url_list": url_list})


# ================================================================== 接口 ==================================================================

# 接口 增删改查 位运算优化 分页、排序、过滤

class ResourceInterfaceListView(APIView):
    def get(self, request):
        # 分页
        paginator = PageNumberPagination()
        paginator.page_size = 10  # 每页显示数量，可按需调整

        # 获取排序参数，例如?ordering=name 表示按资源名称排序
        ordering = request.query_params.get('ordering', 'id')

        # 初始查询集为所有资源
        queryset = ResourceModel.objects.all()

        # 过滤参数处理，假设前端传来的格式如 key:value 用逗号分隔多个条件，例如 name:res1,pid:1
        filter_params = request.query_params.get('filter', '')
        if filter_params:
            filter_conditions = [f.strip().split(':') for f in filter_params.split(',')]
            q_objects = Q()
            for condition in filter_conditions:
                key, value = condition
                if key == 'name':
                    q_objects &= Q(name__icontains=value)
                elif key == 'pid':
                    try:
                        parent_resource = ResourceModel.objects.get(id=value)
                        q_objects &= Q(pid=parent_resource)
                    except ResourceModel.DoesNotExist:
                        continue
            queryset = queryset.filter(q_objects)

        # 应用排序
        queryset = queryset.order_by(ordering)

        # 进行分页
        result_page = paginator.paginate_queryset(queryset, request)

        # 序列化资源数据，需自行定义对应的序列化器 ResourceSerializer
        serializer = ResourceSerializer(result_page, many=True)
        data = paginator.get_paginated_response(serializer.data)
        return data

class ResourceInterfaceCreateView(APIView):
    def post(self, request):
        name = request.data.get('name')
        pid = request.data.get('pid')

        # 检查资源名称是否符合要求等基础验证

        # 处理父级资源关联
        parent_resource = None
        if pid:
            try:
                parent_resource = ResourceModel.objects.get(id=pid)
            except ResourceModel.DoesNotExist:
                return Response({"message": "父级资源不存在", "status":"400"})

        # 检查是否与已有资源存在互斥（这里简单示例，可根据实际细化逻辑）
        all_resources = ResourceModel.objects.all()
        for resource in all_resources:
            if MutexModel.objects.filter(
                    (Q(resource1=resource) & Q(resource2__name=name)) |
                    (Q(resource2=resource) & Q(resource1__name=name))
            ).exists():
                return Response({"message": "与已有资源存在互斥情况", "status":"400"})

        # 创建资源实例
        new_resource = ResourceModel(
            name=name,
            pid=parent_resource
        )
        new_resource.save()

        return Response({"message": "资源创建成功", "resource_id": new_resource.id, "status":"201"})

class ResourceInterfaceUpdateView(APIView):
    def put(self, request, resource_id):
        try:
            resource = ResourceModel.objects.get(id=resource_id)
        except ResourceModel.DoesNotExist:
            return Response({"message": "资源不存在", "status":"404"})

        name = request.data.get('name')
        pid = request.data.get('pid')

        # 处理资源名称唯一性等验证（如果名称有变化）

        # 处理父级资源变更
        new_parent_resource = None
        if pid:
            try:
                new_parent_resource = ResourceModel.objects.get(id=pid)
            except ResourceModel.DoesNotExist:
                return Response({"message": "新父级资源不存在", "status":"400"})

        # 检查更新后是否产生资源互斥（和创建类似，比较复杂情况需更精细逻辑）
        current_related_resources = ResourceModel.objects.exclude(id=resource_id)
        for related_resource in current_related_resources:
            if MutexModel.objects.filter(
                    (Q(resource1=related_resource) & Q(resource2__name=name)) |
                    (Q(resource2=related_resource) & Q(resource1__name=name))
            ).exists():
                return Response({"message": "更新后与其他资源存在互斥情况", "status":"400"})

        # 更新资源属性
        resource.name = name if name else resource.name
        resource.pid = new_parent_resource if new_parent_resource else resource.pid
        resource.save()

        return Response({"message": "资源更新成功", "status":"200"})

class ResourceInterfaceDeleteView(APIView):
    def delete(self, request, resource_id):
        try:
            resource = ResourceModel.objects.get(id=resource_id)
        except ResourceModel.DoesNotExist:
            return Response({"message": "资源不存在", "status":"404"})

        # 检查是否有子资源关联该资源，如果有，根据业务决定如何处理，这里简单提示
        if ResourceModel.objects.filter(pid=resource).exists():
            return Response({"message": "存在子资源关联，不能直接删除该资源", "status":"400"})

        # 检查是否被角色关联，如果有，同样按业务规则处理，这里暂简单提示
        if RoleModel.objects.filter(resources=resource).exists():
            return Response({"message": "资源被角色关联，不能直接删除该资源", "status":"400"})

        resource.delete()

        return Response({"message": "资源删除成功", "status":"204"})
